package com.cancer.common.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;

import sun.misc.BASE64Encoder;

/**
 * 
 * @author 刘俊
 * @time 2015年5月6日
 */
public class FileUtil {
	public static final String[] imageTypes = {"png", "jpg", "jpeg", "jpe", "jfif", "gif", "bmp", "tif", "tiff"};

	/**
	 * 判断文件的父目录是否存在，不存在则创建
	 * 
	 * @author 刘俊 2014年9月9日
	 * @param filePath 文件的路径. 
	 */
	public static void createFileFolderIfNotExist(String filePath) {
		File dir = new File(filePath.substring(0, filePath.lastIndexOf("/")));
		if ( !dir.exists() ) {
			dir.mkdirs();
		}
	}
	/**
	 * 判断目录是否存在，不存在则创建
	 * 
	 * @author 刘俊 2014年9月9日
	 * @param filePath 目录路径. 
	 */
	public static void createFolderIfNotExist(String dirPath) {
		File dir = new File(dirPath);
		if ( !dir.exists() ) {
			dir.mkdirs();
		}
	}
	
	/**
	 * 拷贝文件夹
	 * 
	 * @param src 	源路径
	 * @param dest	目标路径
	 * @throws IOException
	 * @throws FileNotFoundException
	 */
	public static void copyDir(String srcPath, String destPath) throws FileNotFoundException, IOException {
		// 拒绝自己拷贝给自己
		if (srcPath.equals(destPath)) {
			return;
		}
		File src = new File(srcPath);
		File dest = new File(destPath);
		copyDir(src, dest);
	}

	/**
	 * 拷贝文件夹
	 * 
	 * @param src	源File对象
	 * @param dest	目标File对象
	 * @throws IOException
	 * @throws FileNotFoundException
	 */
	public static void copyDir(File src, File dest) throws FileNotFoundException, IOException {
		if (src.isDirectory()) { // 文件夹
			dest = new File(dest, src.getName());
			if (dest.getAbsolutePath().contains(src.getAbsolutePath())) {
				System.out.println("父目录不能拷贝到子目录中");
				return;
			}
		}
		copyDirDetail(src, dest);
	}

	/**
	 * 拷贝文件夹细节
	 * 
	 * @param src
	 * @param dest
	 */
	public static void copyDirDetail(File src, File dest) throws FileNotFoundException, IOException {
		if (src.isFile()) { // 文件
			FileUtil.copyFile(src, dest);
		} else if (src.isDirectory()) { // 文件夹
			// 确保目标文件夹存在
			dest.mkdirs();
			// 获取下一级目录|文件
			for (File sub : src.listFiles()) {
				copyDirDetail(sub, new File(dest, sub.getName()));
			}
		}
	}

	/**
	 * 文件的拷贝
	 * 
	 * @param 源文件路径
	 * @param 目录文件路径
	 * @throws FileNotFoundException
	 *             ,IOException
	 * @return
	 */
	public static void copyFile(String srcPath, String destPath) throws FileNotFoundException, IOException {
		// 1、建立联系 源(存在且为文件) +目的地(文件可以不存在)
		copyFile(new File(srcPath), new File(destPath));
	}

	/**
	 * 文件的拷贝
	 * 
	 * @param 源文件File对象
	 * @param 目录文件File对象
	 * @throws FileNotFoundException, IOException
	 * @return
	 */
	public static void copyFile(File src, File dest) throws FileNotFoundException, IOException {
		if (!src.isFile()) { // 不是文件或者为null
			throw new IOException("只能拷贝文件");
		}
		// dest为已经存在的文件夹，不能建立于文件夹同名的文件
		if (dest.isDirectory()) {
			throw new IOException(dest.getAbsolutePath() + "不能建立于文件夹同名的文件");
		}

		// 2、选择流
		InputStream is = new BufferedInputStream(new FileInputStream(src));
		OutputStream os = new BufferedOutputStream(new FileOutputStream(dest));
		// 3、文件拷贝 循环+读取+写出
		byte[] flush = new byte[1024];
		int len = 0;
		// 读取
		while (-1 != (len = is.read(flush))) {
			// 写出
			os.write(flush, 0, len);
		}
		os.flush(); // 强制刷出

		// 关闭流
		os.close();
		is.close();
	}
	
	/**
	 * 将一个input流转成文件
	 * 
	 * @author 刘俊 2015年6月17日
	 * @param is
	 * @param savePath
	 * @throws IOException
	 */
	public static void toFile(InputStream is, String savePath) throws IOException {
		File file = new File(savePath);
		
		OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
		// 文件拷贝 循环+读取+写出
		byte[] flush = new byte[1024];
		int len = 0;
		while (-1 != (len = is.read(flush))) { 	// 读取
			os.write(flush, 0, len); 			// 写出
		}
		os.flush();								// 强制刷出

		// 关闭流
		os.close();
		is.close();
	}
	
	/**
	 * 将一个input流转成文件
	 * 
	 * @author 刘俊 2015年6月17日
	 * @param is
	 * @param savePath
	 * @throws IOException
	 */
	public static void toFile(byte[] data, String savePath) throws IOException {
		File file = new File(savePath);
		
		// 文件拷贝 循环+读取+写出
		OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
		os.write(data, 0, data.length); // 写出
		os.flush(); 					// 强制刷出
		
		// 关闭流
		os.close();
	}
	
	/**
	 * 根据给定的文件名，获取其扩展名。 若不存在扩展名，则原值返回
	 * @author 刘俊
	 * @time 2015年2月1日
	 * @param fileName
	 * @return
	 */
	public static String getFileExtension(String fileName) {
		
		return fileName.substring(fileName.lastIndexOf(".") + 1) ;
	}
	
	/**
	 * 根据给定的文件名，获取文件名（去掉扩展名）。若没有扩展名，则原值返回
	 * @author 刘俊
	 * @time 2015年2月1日
	 * @param fileName
	 * @return
	 */
	public static String getFileName(String fileName) {
		
		return fileName.substring(0, fileName.lastIndexOf(".") == -1 ? fileName.length() : fileName.lastIndexOf(".")) ;
	}
	
	/**
	 * 判断文件类型是否为图片类型
	 * @author 刘俊
	 * @time 2015年2月1日
	 * @param ext
	 * @return
	 */
	public static boolean isImage(String ext) {
		boolean flag = false;
		for (String type : imageTypes) {
			if(type.equalsIgnoreCase(ext)) {
				flag = true;
				break;
			}
		}
		return flag;
	}
	
	/**
	 * 根据路径删除文件
	 * 
	 * @author 刘俊 2015年5月21日
	 * @param filePath
	 */
	public static void deleteFile(String filePath) {
		File file = new File(filePath);
		deleteFile(file);
	}
	
	/**
	 * 删除文件
	 * 
	 * @author 刘俊 2015年5月21日
	 * @param file
	 */
	public static void deleteFile(File file) {
		if (file.exists() && file.isFile()) {
			file.delete();
		}
	}
	
	/**
	 * 删除空文件夹
	 * 
	 * @author 刘俊 2015年5月21日
	 * @param dir
	 * @return 
	 */
	public static boolean deleteEmptyDir(File dir) {
		if (dir.exists() && dir.isDirectory()) {
			return dir.delete();
		}
		
		return false;
	}
	
	/**
	 * 删除文件夹及其文件
	 * 
	 * @author 刘俊 2015年5月21日
	 * @param dir
	 * @return 
	 */
	public static boolean deleteDir(File dir) {
		if (dir.exists() && dir.isDirectory()) {
			return deleteFileOrDir(dir);
		}
		
		return false;
	}
	
	private static boolean deleteFileOrDir(File file) {
		if (file.isFile()) {
			return file.delete();
		} else {
			File[] files = file.listFiles();
			for (File f : files) {
				deleteFileOrDir(f);
			}
			return file.delete();
		}
	}

	/**
	 * 格式化路径
	 * 
	 * @author 刘俊 2015年9月25日
	 * @param strings
	 * @return
	 */
	public static String formatPath(String ... strings) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < strings.length; ++i) {
			String str = strings[i];
			if (i == strings.length - 1) {
				// 最后一个路径不自动加上'/'
				sb.append(str);
				break;
			}
			sb.append(str + "/");
		}

		String path = sb.toString(); sb = null;
		if (File.separatorChar == '/') {
			path = path.replaceAll("[/|\\\\]+", "/");
		} else {
			path = path.replaceAll("[/|\\\\]+", "\\\\");
		}
		
		return path;
	}
	
	/**
	 * 下载文件时，针对不同浏览器，进行附件名的编码
	 * 
	 * @param filename  下载文件名
	 * @param agent  客户端浏览器
	 * @return 编码后的下载附件名
	 * @throws IOException
	 */
	@SuppressWarnings("restriction")
	public static String encodeDownloadFilename(String filename, String agent)
			throws IOException {
		if (agent.contains("Firefox")) { // 火狐浏览器
			filename = "=?UTF-8?B?"
					+ new BASE64Encoder().encode(filename.getBytes("utf-8"))
					+ "?=";
			filename = filename.replaceAll("\r\n", "");
		} else { // IE及其他浏览器
			filename = URLEncoder.encode(filename, "utf-8");
			filename = filename.replace("+"," ");
		}
		return filename;
	}
}
